from env import Env
from util import Ipc, PathUtil
import base64
import matplotlib.pyplot as plt
from io import BytesIO
import threading
import os

# 配置 matplotlib 图表样式
plt.rcParams['figure.dpi'] = 300  # 提高图表分辨率
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['SimHei']  # 支持中文显示
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题


def generate_html_report(host_data):
    """
    生成 HTML 报告
    :param host_data: 包含主机信息和对应图表 Base64 编码的字典列表
    :return: 完整的 HTML 内容
    """
    flush_interval = Env.get_flush_interval("process")
    html_content = f"""
         <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="refresh" content="{flush_interval}">
    """
    # 定义 HTML 头部和 CSS 样式
    html_content += """
        <style>
            body {
                font-family: Arial, sans-serif;
                background-color: #f4f4f4;
                margin: 20px;
            }
            .host-container {
                display: flex;
                flex-wrap: wrap;
                gap: 20px; /* 主机之间的间距 */
            }
            .host-item {
                flex: 0 0 calc(50% - 10px); /* 每个主机项占据宽度的一半，并减去间距 */
            }
            img {
                display: block;
                border: 1px solid #ddd;
                border-radius: 4px;
                box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
                width: 100%; /* 宽度占满主机项 */
                height: auto; /* 高度自适应 */
            }
            p {
                color: #666;
            }
        </style>
    </head>
    <body>
    <div class="host-container">
    """
    for host_info in host_data:
        host = host_info["host"]
        plot_url = host_info.get("plot_url")
        if plot_url:
            html_content += f'<div class="host-item">'
            html_content += f'<img src="data:image/png;base64,{plot_url}">'
            html_content += '</div>'
        else:
            html_content += f'<div class="host-item"><p>执行命令未返回有效结果。</p></div>'

    html_content += """
    </div>
    </body>
    </html>
    """
    return html_content


def scan():
    """
    进程检查，检查
    :return:
    """
    host_data = []
    for host_info in Env.get_host_list():
        host = host_info["host"]
        if host_info.get("process") is None or host_info.get("process").get("cmd") is None:
            continue
        cmd = host_info.get("process").get("cmd")
        flush_interval = host_info.get("process").get("flush_interval")
        result = Ipc.shell_call_new(host, cmd)

        if result:
            lines = result.splitlines()
            headers = lines[0].split()
            data = []
            for line in lines[1:]:
                values = line.split(None, len(headers) - 1)
                process_info = dict(zip(headers, values))
                data.append(process_info)

            # 提取 CPU 和内存占用比例
            cpu_percentages = [float(process.get("%CPU", 0)) for process in data]
            mem_percentages = [float(process.get("%MEM", 0)) for process in data]

            # 生成直方图
            fig, ax = plt.subplots(figsize=(10, 6))  # 设置图表大小
            bar_width = 0.35
            index = range(len(data))
            cpu_bars = ax.bar(index, cpu_percentages, bar_width, label='CPU %', color='skyblue')
            mem_bars = ax.bar([i + bar_width for i in index], mem_percentages, bar_width, label='Memory %',
                              color='salmon')

            # 添加数据标签
            def add_labels(bars):
                for bar in bars:
                    height = bar.get_height()
                    ax.annotate(f'{height:.2f}',
                                xy=(bar.get_x() + bar.get_width() / 2, height),
                                xytext=(0, 3),  # 3 points vertical offset
                                textcoords="offset points",
                                ha='center', va='bottom')

            add_labels(cpu_bars)
            add_labels(mem_bars)

            ax.set_xlabel('进程命令', fontsize=12)
            ax.set_ylabel('占用百分比', fontsize=12)
            ax.set_title(f'{host} 的 CPU 和内存使用情况', fontsize=16)
            ax.set_xticks([i + bar_width / 2 for i in index])
            ax.set_xticklabels([process.get("COMMAND", "")[:15] for process in data], rotation=45, ha='right',
                               fontsize=10)
            ax.legend()

            # 设置 y 轴范围，最大为 100
            ax.set_ylim(0, 100)

            # 将图表保存为 Base64 编码的字符串
            img = BytesIO()
            plt.savefig(img, format='png', bbox_inches='tight')
            img.seek(0)
            plot_url = base64.b64encode(img.getvalue()).decode()

            host_data.append({"host": host, "plot_url": plot_url})

            plt.close()
        else:
            host_data.append({"host": host, "plot_url": None})

    # 生成 HTML 报告
    html_content = generate_html_report(host_data)

    # 保存 HTML 报告
    report_path = PathUtil.get_root_path() + "/report/process_report.html"
    report_dir = os.path.dirname(report_path)
    if not os.path.exists(report_dir):
        os.makedirs(report_dir)
    with open(report_path, 'w', encoding="utf-8") as file:
        file.write(html_content)


if __name__ == '__main__':
    scan()
